"use client"; import * as React from "react"; import { useActionState, useState } from "react"; import { executeSqlAction, type QueryResultState } from "./actions"; import { Textarea } from "@/components/ui/textarea"; import { Button } from "@/components/ui/button"; import { toast } from "sonner"; // CSV 변환 유틸 function convertToCSV(columns: string[], rows: Record[]): string { const escape = (value: any) => { if (value === null || value === undefined) return ""; const str = String(value).replace(/"/g, '""'); return `"${str}"`; }; const header = columns.map(escape).join(","); const lines = rows.map((row) => columns.map((col) => escape(row[col])).join(",") ); return [header, ...lines].join("\r\n"); } // ──────────────────────────────────────────────────────────────────────────────── // Main page component // ──────────────────────────────────────────────────────────────────────────────── export default function SqlEditorPage() { const [query, setQuery] = useState(""); const initialState: QueryResultState = { columns: [], rows: [], }; // useActionState: 서버 액션과 클라이언트 상태 연결 const [state, formAction, isPending] = useActionState< QueryResultState, FormData >(executeSqlAction, initialState); // CSV 내보내기 핸들러 const handleExportCSV = React.useCallback(() => { if (state.rows.length === 0) { toast.info("내보낼 결과가 없습니다."); return; } const csv = convertToCSV(state.columns, state.rows); const blob = new Blob([csv], { type: "text/csv;charset=euc-kr;" }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = "query_result.csv"; link.click(); URL.revokeObjectURL(url); }, [state.columns, state.rows]); // 오류 toast 표시 React.useEffect(() => { if (state.error) { toast.error(state.error); } }, [state.error]); return (
{/* 상단: 쿼리 입력 영역 */}